package twoD.hofem.Q;

import twoD.hofem.HierarchicFB;
import twoD.hofem.LinearCombinationRToRn;

/**
 * Edge objects represent edges of the finite element mesh and have a geometry
 * and shape function.
 * 
 * @author Team 2
 * 
 */

public class Edge extends MeshPartP {

	private HierarchicFB basis_;
	private EdgeFunction geometry_;
	private Node n1_, n2_;

	/**
	 * Sets the nodes and a straight edge function as geometry
	 */

	public Edge(Node n1, Node n2) {
		n1_ = n1;
		n2_ = n2;
		basis_ = new HierarchicFB();
		geometry_ = new StraightEf();
		setGeometry(geometry_);

	}

	/**
	 * Returns the number of edge shape functions which is p − 1
	 */

	public int countModes() {
		int p = getP() - 1;
		return p;
	}

	/**
	 * Returns a matrix of 3 rows where the first 2 rows contain the dof numbers
	 * of the two nodes and the third row contains the dof numbers of the edge.
	 */

	public int[][] getAllDofNumbers() {

		int[][] result = new int[3][];
		result[0] = n1_.getDofNumbers();
		result[1] = n2_.getDofNumbers();
		result[2] = this.getDofNumbers();
		return result;
	}

	/**
	 * returns the basis
	 */

	public HierarchicFB getBasis() {
		return basis_;
	}

	/**
	 * returns the node this edge has in common with the specified node. if
	 * there is no common node, null is returned
	 */

	public Node getCommonNode(Edge e) {
		Node n = null;

		if (e.n1_ == n1_ || e.n2_ == n1_)
			n = n1_;
		else if (e.n2_ == n2_ || e.n1_ == n2_)
			n = n2_;
		else
			throw new IllegalArgumentException("No common nodes");

		return n;

	}

	/**
	 * returns the Node for the given edge
	 * 
	 * @param idx
	 *            0 or 1
	 * @return {@link Node}
	 */
	public Node getNode(int idx) {

		if (idx == 0)
			return n1_;
		else if (idx == 1)
			return n2_;
		else
			throw new IllegalArgumentException("Index must be 0 or 1");

	}

	/**
	 * returns the linear combination representing approximate solution along
	 * this edge
	 * 
	 * @return {@link LinearCombinationRToRn}
	 */
	public LinearCombinationRToRn getSolution() {
		double[] uLocal = this.getULocal();

		LinearCombinationRToRn b = new LinearCombinationRToRn(getD() , basis_);
		b.setCoefficients(uLocal);
		return b;

	}

	/**
	 * sets the polynomial degree of the basis functions
	 */
	public void setP(int p) {
		basis_.setP(p);

	}

	/**
	 * returns the polynomial degree of the basis functions
	 */

	public int getP() {
		return basis_.getP();
	}

	/**
	 * returns the geometry
	 * 
	 * @return {@link EdgeFunction}
	 */

	public EdgeFunction getGeometry() {

		return geometry_;
	}

	/**
	 * sets the geometry
	 * 
	 * @param g
	 *            {@link EdgeFunction}
	 */

	public void setGeometry(EdgeFunction g) {
		geometry_ = g;
		g.setPoints(n1_.getPosition(), n2_.getPosition());
	}

}
